package org.wattdepot.cli.commands;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * This class writes to a file giving the power generated or consumed for the given amount of days.
 * 
 * Modified by David Mau
 * @author Nate
 * 
 */
public class PowerChartCommand implements WattDepotCliCommand {
  // Default client-server connection to use unless given one.
  private WattDepotClient client = new WattDepotClient(debug);
  
  /**
   * This constructor makes sure that the client really is connected to the server.
   * 
   * @param anotherClient Specifies if the user wants to use another WattDepot server
   * other than the default simulation one.
   */
  public PowerChartCommand( String anotherClient ) {
    // If another client is provided
    if ( anotherClient != null ) {
      client = new WattDepotClient( anotherClient );
    }
    
    // Stop right away if we cannot contact server.
    if (!client.isHealthy()) {
      System.out.println("Failed to connect to " + client.getWattDepotUri());
      return;
    }
    // Indicate successful connection.
    //System.out.println("Connected to " + client.getWattDepotUri());
  }

  /**
   * This method writes to a file giving the power generated or consumed for the given amount of
   * days.
   * 
   * Created by Nathaniel Ashe
   * 
   * @param args Arguments for this command.
   * @return A string confirming file is written.
   */
  public String doCommand(List<String> args) {
    String output = "";
    if (args.size() > 6) {
      output = tooManyArguments;
      output = output.concat(cr);
      return output;
    }
    if (args.size() < 6) {
      output = missingArguments;
      output = output.concat(cr);
      return output;
    }

    String powerWhat = args.get(0);
    String source = args.get(1);
    String dayStart = args.get(2);
    String dayEnd = args.get(3);
    String minutes = args.get(4);
    String file = args.get(5);
    
    int interval;
    try {
      interval = Integer.valueOf(minutes);
    }
    catch (NumberFormatException e) {
      output = intervalNotNumber;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }
    // If the converted integer is negative or zero, return an error.
    if (interval <= 0) {
      output = intervalNegativeOrZero;
      output = output.concat(cr);
      return output;
    }
    
    XMLGregorianCalendar xmlTimeStart = null;
    try {
      xmlTimeStart = Tstamp.makeTimestamp(dayStart);
    }
    catch (Exception e) {
      output = badTimeStamp;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }
    XMLGregorianCalendar xmlTimeEnd = null;
    try {
      xmlTimeEnd = Tstamp.makeTimestamp(dayEnd);
    }
    catch (Exception e) {
      output = badTimeStamp;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }
    
    int temporalTest = xmlTimeStart.compare(xmlTimeEnd);
    if (temporalTest == DatatypeConstants.GREATER) {
      output = endDateBeforeStartDate;
      output = output.concat(cr);
      return output;
    }
    
    Double power = 0.0;
    StringBuffer outputFinal = new StringBuffer(300);

    outputFinal.append("<html><body><img src="
        + "http://chart.apis.google.com/chart?chs=250x100&cht=lc&chd=t:");

    if (powerWhat.compareTo("generated") == 0) {
      while (xmlTimeStart.getDay() < xmlTimeEnd.getDay()) {
        try {
          power = client.getPowerGenerated(source, xmlTimeStart) / 1000000;
        }
        catch (NotAuthorizedException e) {
          output = notAuthorized;
          output = output.concat(e.toString());
          output = output.concat(cr);
          return output;
        }
        catch (ResourceNotFoundException e) {
          output = resourceNotFound;
          output = output.concat(e.toString());
          output = output.concat(cr);
          return output;
        }
        catch (BadXmlException e) {
          output = badXml;
          output = output.concat(e.toString());
          output = output.concat(cr);
          return output;
        }
        catch (MiscClientException e) {
          output = miscClient;
          output = output.concat(e.toString());
          output = output.concat(cr);
          return output;
        }

        outputFinal.append(power);
        outputFinal.append(',');
        xmlTimeStart = Tstamp.incrementMinutes(xmlTimeStart, interval);
      }
      outputFinal.deleteCharAt(outputFinal.length() - 1);
      outputFinal.append("&chds=0.0,54.0&chxt=y&chxr=0,0.0,54.0></body></html>");
    }
    else if (powerWhat.compareTo("consumed") == 0) {
      while (xmlTimeStart.getDay() < xmlTimeEnd.getDay()) {
        try {
          power = client.getPowerConsumed(source, xmlTimeStart) / 1000000;
        }
        catch (NotAuthorizedException e) {
          output = notAuthorized;
          output = output.concat(e.toString());
          output = output.concat(cr);
          return output;
        }
        catch (ResourceNotFoundException e) {
          output = resourceNotFound;
          output = output.concat(e.toString());
          output = output.concat(cr);
          return output;
        }
        catch (BadXmlException e) {
          output = badXml;
          output = output.concat(e.toString());
          output = output.concat(cr);
          return output;
        }
        catch (MiscClientException e) {
          output = miscClient;
          output = output.concat(e.toString());
          output = output.concat(cr);
          return output;
        }

        outputFinal.append(power);
        outputFinal.append(',');
        xmlTimeStart = Tstamp.incrementMinutes(xmlTimeStart, interval);
      }
      outputFinal.deleteCharAt(outputFinal.length() - 1);
      outputFinal.append("&chds=0.0,54.0&chxt=y&chxr=0,0.0,54.0></body></html>");
    }
    else {
      output = generatedOrConsumed;
      output = output.concat(cr);
      return output;
    }
    
    try {
      FileWriter outputFile = new FileWriter(file);
      BufferedWriter out = new BufferedWriter(outputFile);

      out.write(outputFinal.toString());
      out.close();
      output += "Saved to file.";
      return output;
    }
    catch (IOException e1) {
      output = badFile;
      output = output.concat(e1.toString());
      output = output.concat(cr);
      return output;
    }
    
  }
}
